package com.ssy.lingxi.contract.serviceimpl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.contract.entity.ContractInnerRecordDO;
import com.ssy.lingxi.contract.entity.QContractDO;
import com.ssy.lingxi.contract.entity.QContractInnerRecordDO;
import com.ssy.lingxi.contract.model.dto.OperateLogInnerResponDto;
import com.ssy.lingxi.contract.model.dto.OperateLogInputDto;
import com.ssy.lingxi.contract.model.vo.common.request.ContractInnerRecordPageVO;
import com.ssy.lingxi.contract.model.vo.coordination.response.ContractCoordinationInnerRecordVO;
import com.ssy.lingxi.contract.model.vo.manage.response.ContractManageInnerRecordVO;
import com.ssy.lingxi.contract.repository.ContractInnerRecordRepository;
import com.ssy.lingxi.contract.service.IContractInnerRecordService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 合同内部流转记录接口实现
 * @author 伍将
 * @date 2021/2/7
 * @version 2.0.0
 */
@Service
public class ContractInnerRecordServiceImpl implements IContractInnerRecordService {

    @Resource
    private ContractInnerRecordRepository innerRecordRepository;
    @Resource
    private JPAQueryFactory jpaQueryFactory;
    /**
     * 新增外部流转记录
     * @author 伍将
     * @date 2021/2/7
     * @param user: 新增外部流转记录
     * @param contractId: 合同id
     * @param status: 状态
     * @param statusName: 状态名称
     * @param operate: 操作
     * @param opinion: 意见
     * @return 操作结果
     **/
    @Override
    public Wrapper<Void> add(UserLoginCacheDTO user, Long contractId, Integer status, String statusName, String operate, String opinion) {

        ContractInnerRecordDO recordDO = new ContractInnerRecordDO();
        recordDO.setContractId(contractId);
        recordDO.setUserId(user.getUserId());
        recordDO.setMemberId(user.getMemberId());
        recordDO.setRoleId(user.getMemberRoleId());
        recordDO.setOperator(user.getUserName());
        recordDO.setDepartment(user.getUserOrgName());
        recordDO.setJobTitle(user.getUserJobTitle());
        recordDO.setStatus(status);
        recordDO.setStatusName(statusName);
        recordDO.setOperate(operate);
        recordDO.setOperateTime(System.currentTimeMillis());
        recordDO.setOpinion(opinion);

        innerRecordRepository.saveAndFlush(recordDO);

        return Wrapper.success();
    }

    /**
     * 分页查询合同管理下的内部流转记录
     * @author 伍将
     * @date 2021/2/24
     * @param user: 当前登录用户
     * @param pageVO: 分页请求参数
     * @return 操作结果
     **/
    @Override
    public Wrapper<PageData<ContractManageInnerRecordVO>> pageManageList(UserLoginCacheDTO user, ContractInnerRecordPageVO pageVO) {
        // 组装查询条件
        Specification<ContractInnerRecordDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("contractId").as(Long.class), pageVO.getContractId()));
            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), user.getMemberRoleId()));

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("operateTime").ascending());

        Page<ContractInnerRecordDO> recordList = innerRecordRepository.findAll(spec, page);
        List<ContractManageInnerRecordVO> resultList = recordList.stream().map(r -> {
            ContractManageInnerRecordVO entity = new ContractManageInnerRecordVO();
            entity.setOperator(r.getOperator());
            entity.setDepartment(r.getDepartment());
            entity.setJobTitle(r.getJobTitle());
            entity.setStatus(r.getStatus());
            entity.setStatusName(r.getStatusName());
            entity.setOperate(r.getOperate());
            entity.setOperateTime(DateUtil.format(DateUtil.date(r.getOperateTime()), "yyyy-MM-dd HH:mm"));
            entity.setOpinion(r.getOpinion());
            return entity;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(recordList.getTotalElements(), resultList));
    }

    /**
     * 分页查询合同协作下的内部流转记录
     * @author 伍将
     * @date 2021/2/25
     * @param user: 当前登录用户
     * @param pageVO: 分页请求参数
     * @return 操作结果
     **/
    @Override
    public Wrapper<PageData<ContractCoordinationInnerRecordVO>> pageCoordinationList(UserLoginCacheDTO user, ContractInnerRecordPageVO pageVO) {
        // 组装查询条件
        OperateLogInputDto dto=new OperateLogInputDto();
        dto.setContractId(pageVO.getContractId());
        dto.setPageSize(pageVO.getPageSize());
        dto.setCurrent(pageVO.getCurrent());
        PageData<OperateLogInnerResponDto> pageData = pageListCommon(user, dto);
        List<ContractCoordinationInnerRecordVO> resultList =null;
        if(CollectionUtil.isNotEmpty(pageData.getData())){
                resultList = pageData.getData().stream().map(r -> {
                ContractCoordinationInnerRecordVO entity = new ContractCoordinationInnerRecordVO();
                entity.setOperator(r.getOperator());
                entity.setDepartment(r.getDepartment());
                entity.setJobTitle(r.getJobTitle());
                entity.setStatus(r.getStatus());
                entity.setStatusName(r.getStatusName());
                entity.setOperate(r.getOperate());
                entity.setOperateTime(DateUtil.format(DateUtil.date(r.getOperateTime()), "yyyy-MM-dd HH:mm"));
                entity.setOpinion(r.getOpinion());
                return entity;
            }).collect(Collectors.toList());
        }
        return Wrapper.success(new PageData<>(pageData.getTotalCount(), resultList));
    }

    @Override
    public PageData<OperateLogInnerResponDto> pageListCommon(UserLoginCacheDTO loginUser,OperateLogInputDto pageVO) {

        // 查询表实体
        QContractDO contractDO=QContractDO.contractDO;
        QContractInnerRecordDO innerWorkflowRecordDO=QContractInnerRecordDO.contractInnerRecordDO;
        // 查询条件构造
        BooleanBuilder predicates = new BooleanBuilder();
        //合同id
        if(pageVO.getContractId()!=null){
            predicates.and(contractDO.id.eq(pageVO.getContractId()));
        }
        //合同编号
        if(StringUtils.hasLength(pageVO.getContractNo())){
            predicates.and(contractDO.contractNo.eq(pageVO.getContractNo()));
        }
        //时间
        if(pageVO.getStartTime()!=null){
            predicates.and(innerWorkflowRecordDO.operateTime.goe(pageVO.getStartTime()));
        }
        if(pageVO.getEndTime()!=null){
            predicates.and(innerWorkflowRecordDO.operateTime.loe(pageVO.getEndTime()));
        }
        //会员id
        if(loginUser!=null){
            predicates.and(innerWorkflowRecordDO.memberId.eq(loginUser.getMemberId()));
            predicates.and(innerWorkflowRecordDO.roleId.eq(loginUser.getMemberRoleId()));
        }
        // 关联查询
        JPAQuery<OperateLogInnerResponDto> query = jpaQueryFactory
                .select(Projections.bean(OperateLogInnerResponDto.class,
                        contractDO.contractNo,
                        innerWorkflowRecordDO.operator,
                        innerWorkflowRecordDO.department,
                        innerWorkflowRecordDO.jobTitle,
                        innerWorkflowRecordDO.status,
                        innerWorkflowRecordDO.statusName,
                        innerWorkflowRecordDO.operate,
                        innerWorkflowRecordDO.operateTime,
                        innerWorkflowRecordDO.opinion)
                )
                .from(contractDO)
                .innerJoin(innerWorkflowRecordDO)
                .on(contractDO.id.eq(innerWorkflowRecordDO.contractId))
                .where(predicates);

        long totalCount = query.fetchCount();
        List<OperateLogInnerResponDto> responses = query.orderBy(innerWorkflowRecordDO.operateTime.desc())
                .offset(pageVO.getCurrentOffset())
                .limit(pageVO.getPageSize())
                .fetch();
        return new PageData<>(totalCount, responses);
    }
}
